In [1]:
import matplotlib.pyplot as plt
import pandas as pd
import plotly.graph_objs as go
import plotly.express as px
import numpy as np
import os
import sys
import pickle
import seaborn as sns
sns.set_theme(style="whitegrid")
import warnings
warnings.filterwarnings("ignore")

1. Simulation running or results extraction¶

In [2]:
#Run this for simulation

weather_year=2018 #must be between 2017 and 2019
carbon_tax=60
gas_price_coef=1
coal_price_coef=1 
number_of_sub_techs=5
fr_flex_consum={'conso':{"nbVE":5,"steel_twh":5,"H2_twh":25},'ratio':{"VE_ratio":0,"steel_ratio":0,"H2_ratio":0}}

if os.path.basename(os.getcwd()) == "Seven_node_Europe":
    os.chdir('../..')
    
from Main_2030 import *
Variables=main_2030(weather_year,carbon_tax,gas_price_coef,coal_price_coef,number_of_sub_techs,fr_flex_consum)
	 Model creation at 0:00:02.724524
	 Start solving at 0:07:47.030171
	 Solved at 0:19:01.090350
	 Total duration: 0:19:08.678238
In [3]:
#Run this to load a result file
with open("Result_2030.pickle", 'rb') as f:
    Variables=pickle.load(f)

2. Preliminary calculations¶

In [4]:
states=["2030"]
exch_list=[Variables["exchange"]]
data=[Variables["energy"]]
data_stor=[Variables["storageOut"]]
data_capa=[Variables["capacity"]]
data_stor_capa=[Variables["Pmax"]]
consumption=Variables['total_consumption']
consumption["Date"]=pd.to_datetime(consumption["Date"])
consumption.sort_values(by='Date', inplace=True)
consumption.reset_index(inplace=True,drop=True)
colors=["black"]
In [5]:
#subtechs list
l=data_capa[0]
l=l.TECHNOLOGIES.unique()
u=[]
n_list=[]
for tech_name in l:
    if tech_name[:4]=="Coal" and tech_name!="Coal":
        n_list.append(tech_name[4:])

3. Results plot¶

a. Capacity¶

In [6]:
# total_consum=round(consum.areaConsumption.sum()/10**6,2)
tech_list=["OldNuke","NewNuke","Coal","Lignite","CCG","TAC","HydroRiver","HydroReservoir",'HydroStorage',"Biomass",
           "WindOnShore","WindOffShore","Solar","Battery"]



df_capa=pd.DataFrame(columns=["TECHNOLOGIES"]+states)
df_capa["TECHNOLOGIES"]=np.array(tech_list)
# print(len(data))
for i in range(len(data)):
    capa=data_capa[i]
    for t in tech_list:
        t_list=[t]
        if len(n_list)>0:
            for j in range(len(n_list)):
                t_list.append(t+n_list[j])

        if t not in ["HydroStorage","Battery"] :
            val=round(capa[capa.TECHNOLOGIES.isin(t_list)].capacity.to_numpy().sum()/10**3,2)
    #         print(val)
            df_capa.loc[df_capa.TECHNOLOGIES==t,states[i]]=val
        else:
            u=data_stor_capa[i]
            val=round(u[u.STOCK_TECHNO==t].Pmax.to_numpy().sum()/10**3,2)
#             print(val)
            df_capa.loc[df_capa.TECHNOLOGIES==t,states[i]]=val
total_capa=df_capa[states[0]].sum()
In [7]:
df_capa
Out[7]:
TECHNOLOGIES 2030
0 OldNuke 80.43
1 NewNuke 4.6
2 Coal 8.0
3 Lignite 9.1
4 CCG 147.52
5 TAC 14.86
6 HydroRiver 31.0
7 HydroReservoir 34.44
8 HydroStorage 46.68
9 Biomass 13.94
10 WindOnShore 167.01
11 WindOffShore 54.95
12 Solar 212.92
13 Battery 24.42
In [8]:
tech_list=["OldNuke","NewNuke","Coal","Lignite","CCG","TAC","HydroRiver","HydroReservoir",'HydroStorage',"Biomass",
           "WindOnShore","WindOffShore","Solar","Battery"]

for area in ["FR","DE","GB","BE","IT","ES","CH"]:
    print("\nCapacities installed for "+area)
    df_capa=pd.DataFrame(columns=["TECHNOLOGIES"]+states)
    df_capa["TECHNOLOGIES"]=np.array(tech_list)
    # print(len(data))
    for i in range(len(data)):
        capa=data_capa[i]
        capa=capa[capa.AREAS==area]
        for t in tech_list:
            t_list=[t]
            if len(n_list)>0:
                for j in range(len(n_list)):
                    t_list.append(t+n_list[j])

            if t not in ["HydroStorage","Battery"] :
                val=round(capa[capa.TECHNOLOGIES.isin(t_list)].capacity.to_numpy().sum()/10**3,2)
        #         print(val)
                df_capa.loc[df_capa.TECHNOLOGIES==t,states[i]]=val
            else:
                u=data_stor_capa[i]
                u=u[u.AREAS==area]
                val=round(u[u.STOCK_TECHNO==t].Pmax.to_numpy().sum()/10**3,2)
    #             print(val)
                df_capa.loc[df_capa.TECHNOLOGIES==t,states[i]]=val
    print(df_capa)
Capacities installed for FR
      TECHNOLOGIES   2030
0          OldNuke  60.49
1          NewNuke    1.3
2             Coal    0.0
3          Lignite    0.0
4              CCG   6.58
5              TAC    0.7
6       HydroRiver   13.0
7   HydroReservoir    7.0
8     HydroStorage    8.0
9          Biomass    1.5
10     WindOnShore   33.0
11    WindOffShore    5.0
12           Solar   40.0
13         Battery    3.0

Capacities installed for DE
      TECHNOLOGIES   2030
0          OldNuke    0.0
1          NewNuke    0.0
2             Coal    8.0
3          Lignite    9.1
4              CCG   23.3
5              TAC  10.89
6       HydroRiver    3.8
7   HydroReservoir    1.4
8     HydroStorage    9.5
9          Biomass   6.23
10     WindOnShore  60.08
11    WindOffShore   15.0
12           Solar  71.88
13         Battery    0.0

Capacities installed for GB
      TECHNOLOGIES   2030
0          OldNuke    4.0
1          NewNuke    3.3
2             Coal    0.0
3          Lignite    0.0
4              CCG  30.62
5              TAC    1.0
6       HydroRiver    2.0
7   HydroReservoir    0.0
8     HydroStorage    4.3
9          Biomass    0.0
10     WindOnShore   22.0
11    WindOffShore   30.0
12           Solar   17.0
13         Battery   11.7

Capacities installed for BE
      TECHNOLOGIES  2030
0          OldNuke  5.94
1          NewNuke   0.0
2             Coal   0.0
3          Lignite   0.0
4              CCG  7.43
5              TAC  2.27
6       HydroRiver   0.2
7   HydroReservoir   0.0
8     HydroStorage   1.3
9          Biomass   0.4
10     WindOnShore   2.8
11    WindOffShore   2.3
12           Solar   7.8
13         Battery   0.0

Capacities installed for IT
      TECHNOLOGIES   2030
0          OldNuke    0.0
1          NewNuke    0.0
2             Coal    0.0
3          Lignite    0.0
4              CCG   50.0
5              TAC    0.0
6       HydroRiver  10.47
7   HydroReservoir   4.45
8     HydroStorage   11.9
9          Biomass    4.8
10     WindOnShore   12.6
11    WindOffShore    1.0
12           Solar   30.5
13         Battery    6.0

Capacities installed for ES
      TECHNOLOGIES   2030
0          OldNuke    7.4
1          NewNuke    0.0
2             Coal    0.0
3          Lignite    0.0
4              CCG   29.0
5              TAC    0.0
6       HydroRiver    1.0
7   HydroReservoir   16.0
8     HydroStorage   7.89
9          Biomass   0.61
10     WindOnShore  36.35
11    WindOffShore   1.65
12           Solar  36.01
13         Battery    2.5

Capacities installed for CH
      TECHNOLOGIES  2030
0          OldNuke   2.6
1          NewNuke   0.0
2             Coal   0.0
3          Lignite   0.0
4              CCG  0.58
5              TAC   0.0
6       HydroRiver  0.53
7   HydroReservoir  5.59
8     HydroStorage  3.79
9          Biomass   0.4
10     WindOnShore  0.18
11    WindOffShore   0.0
12           Solar  9.73
13         Battery  1.22

b. Production¶

In [9]:
country="FR"
p=Variables["capacity"]
p=p[p.AREAS==country]
p
Out[9]:
AREAS TECHNOLOGIES capacity
66 FR OldNuke 60486.460311
67 FR Biomass6666666666666666 187.500000
68 FR Lignite3333333333333333 0.000000
69 FR WindOffShore 5000.000000
70 FR CCG3333333333333333 823.125000
71 FR TAC8333333333333333 87.875000
72 FR Coal6666666666666666 0.000000
73 FR Biomass 750.000000
74 FR TAC16666666666666666 87.875000
75 FR TAC3333333333333333 87.875000
76 FR Coal 0.000000
77 FR HydroReservoir 7000.000000
78 FR Lignite 0.000000
79 FR TAC6666666666666666 87.875000
80 FR Biomass8333333333333333 187.500000
81 FR WindOnShore 33000.000000
82 FR CCG8333333333333333 823.125000
83 FR Biomass16666666666666666 187.500000
84 FR Lignite6666666666666666 0.000000
85 FR TAC 351.500000
86 FR Lignite16666666666666666 0.000000
87 FR HydroRiver 13000.000000
88 FR Coal16666666666666666 0.000000
89 FR Coal8333333333333333 0.000000
90 FR CCG 3292.500000
91 FR Lignite8333333333333333 0.000000
92 FR CCG6666666666666666 823.125000
93 FR curtailment 5000.000000
94 FR Biomass3333333333333333 187.500000
95 FR NewNuke 1300.000000
96 FR CCG16666666666666666 823.125000
97 FR Coal3333333333333333 0.000000
98 FR Solar 40000.000000

i. Production at the 7 nodes scale¶

In [10]:
# total_consum=round(consum.areaConsumption.sum()/10**6,2)
tech_list=["OldNuke","NewNuke","Coal","Lignite","CCG","TAC","HydroRiver","HydroReservoir",'HydroStorage',"Biomass",
           "WindOnShore","WindOffShore","Solar","Battery","curtailment"]



df_prod=pd.DataFrame(columns=["TECHNOLOGIES"]+states)
df_prod["TECHNOLOGIES"]=np.array(tech_list)

for i in range(len(data)):
    prod=data[i]
    for t in tech_list:
        t_list=[t]
        if len(n_list)>0:
            for j in range(len(n_list)):
                t_list.append(t+n_list[j])

        if t!="HydroStorage":
            val=round(prod[prod.TECHNOLOGIES.isin(t_list)].energy.to_numpy().sum()/10**6,2)
    #         print(val)
            df_prod.loc[df_prod.TECHNOLOGIES==t,states[i]]=val
        else:
            u=data_stor[i]
            val=round(u[u.STOCK_TECHNO==t].storageOut.to_numpy().sum()/10**6,2)

            df_prod.loc[df_prod.TECHNOLOGIES==t,states[i]]=val
total_prod=df_prod[states[0]].sum()
In [11]:
df_prod_bar=pd.DataFrame(columns=["TECHNOLOGIES","Production (TWh)","Production (%)","Scenario"])
for c in df_prod.columns[1:]:
    u=df_prod[["TECHNOLOGIES",c]]
    u.rename(columns={c:"Production (TWh)"},inplace=True)
    u["Production (%)"]=u["Production (TWh)"]/u["Production (TWh)"].sum()*100
    u["Scenario"]=c
    df_prod_bar=pd.concat([df_prod_bar,u],ignore_index=True)
In [12]:
import plotly.express as px
fig = px.bar(df_prod_bar, x='Scenario', y='Production (%)', color="TECHNOLOGIES")
fig.show()
In [13]:
fig = px.pie(df_prod_bar, values='Production (TWh)', names='TECHNOLOGIES', title='Production per technology (in %)')
fig.show()

ii. Production at country scale¶

In [14]:
# total_consum=round(consum.areaConsumption.sum()/10**6,2)
countries=["FR","DE","BE","GB","IT","CH","ES"]
tech_list=["OldNuke","NewNuke","Biomass","Coal","Lignite","CCG","TAC","HydroRiver","HydroReservoir",'HydroStorage','Battery',
            "WindOnShore","WindOffShore","Solar"]



df_prod_country=pd.DataFrame(columns=["AREAS","TECHNOLOGIES","State","Production (TWh)"])


for i in range(len(states)):
    prod=data[i]
    for c in countries:
        for t in tech_list:
            t_list=[t]
            if len(n_list)>0:
                for j in range(len(n_list)):
                    t_list.append(t+n_list[j])
            if t not in ["HydroStorage","Battery"]:
                val=round(prod[(prod.TECHNOLOGIES.isin(t_list)) & (prod.AREAS==c)].energy.to_numpy().sum()/10**6,2)
                array=np.array([[c,t,states[i],val]])
                df_prod_country=pd.concat([df_prod_country,
                                           pd.DataFrame(array,columns=["AREAS","TECHNOLOGIES","State","Production (TWh)"])])
            else:
                u=data_stor[i]
                val=round(u[(u.STOCK_TECHNO==t) & (u.AREAS==c)].storageOut.to_numpy().sum()/10**6,2)
                array=np.array([[c,t,states[i],val]])
                df_prod_country=pd.concat([df_prod_country,
                                           pd.DataFrame(array,columns=["AREAS","TECHNOLOGIES","State","Production (TWh)"])])

df_prod_country["Production (TWh)"]=df_prod_country["Production (TWh)"].astype('float')
                
# comparison_per_country=df_prod_country.copy()
# for country in countries:
#     total_prod=df_prod[states[0]].sum()
#     total_consum=round(consum[consum.AREAS==country].areaConsumption.sum()/10**6,2)
#     comparison_per_country.loc[comparison_per_country.AREAS==country,"Production (TWh)"]= comparison_per_country.loc[comparison_per_country.AREAS==country,"Production (TWh)"].astype(float)/total_consum
    
# comparison_per_country["Difference with historical"]=np.zeros(len(comparison_per_country))
# for state in states:
#     comparison_per_country.loc[comparison_per_country.State==state,"Difference with "+states[0]]=(comparison_per_country.loc[comparison_per_country.State==state,"Production (TWh)"]-comparison_per_country.loc[comparison_per_country.State=="Historical","Production (TWh)"])*100                
In [15]:
from  matplotlib.ticker import PercentFormatter
g = sns.catplot(x="State", y="Production (TWh)",hue="AREAS",col="TECHNOLOGIES",col_wrap=3,kind="bar",
                data=df_prod_country)
# for ax in g.axes.flat:
#     ax.yaxis.set_major_formatter(PercentFormatter())

plt.show()
In [16]:
country="CH"
p=Variables["energy"]
p=p[p.AREAS==country]
storout=Variables["storageOut"]
#print("HydroStorage",round(storout[storout.AREAS==country].storageOut.sum()/10**6,2),"TWh")
storout=storout[(storout.AREAS==country) & (storout.STOCK_TECHNO!="Battery")]
storout=storout.rename(columns={'STOCK_TECHNO':'TECHNOLOGIES',"storageOut":"energy"})
p=pd.concat([p,storout],ignore_index=True)
tot=0
for t in p.TECHNOLOGIES.unique():
    l=p[p.TECHNOLOGIES==t]
    print(t,round(l.energy.sum()/10**6,2),"TWh")
    tot+=l.energy.sum()
print("Total produced",round(tot/10**6,2),"TWh")
OldNuke 18.52 TWh
Biomass6666666666666666 0.03 TWh
Lignite3333333333333333 0.0 TWh
WindOffShore 0.0 TWh
CCG3333333333333333 0.57 TWh
TAC8333333333333333 0.0 TWh
Coal6666666666666666 0.0 TWh
Biomass 0.14 TWh
TAC16666666666666666 0.0 TWh
TAC3333333333333333 0.0 TWh
Coal 0.0 TWh
HydroReservoir 10.62 TWh
Lignite 0.0 TWh
TAC6666666666666666 0.0 TWh
Biomass8333333333333333 0.03 TWh
WindOnShore 0.27 TWh
CCG8333333333333333 0.2 TWh
Biomass16666666666666666 0.04 TWh
Lignite6666666666666666 0.0 TWh
TAC 0.0 TWh
Lignite16666666666666666 0.0 TWh
HydroRiver 1.53 TWh
Coal16666666666666666 0.0 TWh
Coal8333333333333333 0.0 TWh
CCG 1.79 TWh
Lignite8333333333333333 0.0 TWh
CCG6666666666666666 0.37 TWh
curtailment 0.0 TWh
Biomass3333333333333333 0.04 TWh
NewNuke 0.0 TWh
CCG16666666666666666 0.57 TWh
Coal3333333333333333 0.0 TWh
Solar 12.07 TWh
HydroStorage 0.0 TWh
Total produced 46.78 TWh
In [17]:
tech_list=["OldNuke","NewNuke","Biomass","Coal","CCG","HydroRiver","HydroReservoir",'HydroStorage',
           "WindOnShore","WindOffShore","Solar","curtailment"]
sorted_df=pd.DataFrame(columns=["Date","TECHNOLOGIES","energy"])
for i in range(len(tech_list)):
    d=p[p.TECHNOLOGIES==tech_list[i]].sort_values(by="Date")
    sorted_df=pd.concat([sorted_df,d[["Date","TECHNOLOGIES","energy"]]],ignore_index=True)
fig = px.area(sorted_df, x="Date", y="energy", color="TECHNOLOGIES",line_group="TECHNOLOGIES",title=country+" simulations")
consum=consumption[consumption.AREAS==country]
fig.add_scatter(x=consum.Date, y=consum["total_consumption"], name="Consumption",mode="lines",line_color="black")
fig.show()

c. HydroStorage operations¶

In [18]:
stocklevels=[Variables["stockLevel"]]
for area in stocklevels[0].AREAS.unique():
    fig, ax = plt.subplots(1,figsize=(20,10))
    fig.suptitle(area+" Hydrostorage stock level")
    v=stocklevels[0]
    u=v[v.AREAS==area]
    u=u[u.STOCK_TECHNO=="HydroStorage"]
    ax.plot(u.Date,u.stockLevel,"o",color=colors[0],label=states[0])
    ax.legend()
    ax.set_ylabel("Storage (MWh)")
    plt.xlabel("Date")

d. Exchanges¶

In [19]:
c1,c2="FR","CH"

plt.figure(figsize=(10,5))

fig=plt.figure(figsize=(20,5))
plt.title(c1+'-'+c2+" exchanges")
    
u=exch_list[0]
v=u[(u.AREAS==c1)&(u.AREAS1==c2)]
v.TIMESTAMP=pd.to_datetime(v.TIMESTAMP)
plt.scatter(v.TIMESTAMP,v.exchange,label=states[0],s=20,alpha=0.3,color=colors[0])
plt.legend()
plt.ylabel('Exchanges (MW)')
# plt.subplots_adjust(left=None, bottom=0, right=None, top=1, wspace=0.2, hspace=None)
plt.xlabel("Date")
Out[19]:
Text(0.5, 0, 'Date')
<Figure size 720x360 with 0 Axes>
In [20]:
ext_fr=["DE","BE","GB","IT","CH","ES"]
exchanges_fr=pd.DataFrame(columns=["state",'countries',"Exchanges (TWh)"])
other_exchanges=pd.DataFrame(columns=["state",'countries',"Exchanges (TWh)"])

for i in range(len(exch_list)):
    s=0
    exchange=exch_list[i]
    for c in ["DE","BE","GB","IT","CH","ES"]:
        value=round(exchange[(exchange.AREAS=="FR") & (exchange.AREAS1==c)].exchange.sum()/10**6,2)
        s+=value
        u=pd.DataFrame(np.array([[states[i],c,
                                 value]]),
                       columns=["state",'countries',"Exchanges (TWh)"])
        exchanges_fr=pd.concat([exchanges_fr,u],ignore_index=True)

    u=pd.DataFrame(np.array([[states[i],"Total",
                                 s]]),
                       columns=["state",'countries',"Exchanges (TWh)"])
    exchanges_fr=pd.concat([exchanges_fr,u],ignore_index=True)

    for a,b in [["CH","DE"],["CH","IT"],["DE","IT"]]:
        value=round(exchange[(exchange.AREAS==a) & (exchange.AREAS1==b)].exchange.sum()/10**6,2)
        u=pd.DataFrame(np.array([[states[i],a+"-"+b,
                                 value]]),
                       columns=["state",'countries',"Exchanges (TWh)"])
        other_exchanges=pd.concat([other_exchanges,u],ignore_index=True)
        
exchanges_fr["Exchanges (TWh)"]=exchanges_fr["Exchanges (TWh)"].astype(float)
other_exchanges["Exchanges (TWh)"]=other_exchanges["Exchanges (TWh)"].astype(float)
In [21]:
ax = sns.barplot(x="countries", y="Exchanges (TWh)", hue="state",data=exchanges_fr)
ax.title.set_text("France exchanges")
In [22]:
ax = sns.barplot(x="countries", y="Exchanges (TWh)", hue="state",data=other_exchanges)
ax.title.set_text("Other exchanges")

e. Cost¶

In [23]:
capacityCost=np.array([Variables['capacityCosts'].capacityCosts.sum()/10**9])
In [24]:
energyCost=np.array([Variables['energyCosts'].energyCosts.sum()/10**9])
In [25]:
ax=sns.barplot(x=["Scenario"],y=capacityCost)
plt.ylabel("B€/year")
plt.title("Annualized capacity cost")
ax.bar_label(ax.containers[0])
Out[25]:
[Text(0, 0, '94.3188')]
In [26]:
ax=sns.barplot(x=["Scenario"],y=energyCost)
plt.ylabel("B€/year")
plt.title("Annualized energy cost")
ax.bar_label(ax.containers[0])
Out[26]:
[Text(0, 0, '32.5335')]
In [27]:
ax=sns.barplot(x=["Scenario"],y=energyCost+capacityCost)
plt.ylabel("B€/year")
plt.title("Annualized total cost")
ax.bar_label(ax.containers[0])
Out[27]:
[Text(0, 0, '126.852')]
In [28]:
tot_cost=energyCost+capacityCost
ax=sns.barplot(x=["Scenario"],y=tot_cost*10**9/np.array([total_prod])*10**-6)
plt.ylabel("€/MWh")
plt.title("Cost of electricity")
ax.bar_label(ax.containers[0])
Out[28]:
[Text(0, 0, '62.22')]